﻿/*
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * See product pages for more information.
 * http://closesudoku.codeplex.com
 * Copyright (C), 2010, hrondra
 */
using System;
using System.Collections.Generic;
using System.Text;
using Fluid.Controls;
using System.Drawing;
using Close.Properties;

using Fluid.Drawing;
using Fluid.Classes.Theme;
using Close.Classes;

namespace Close.Controls
{
    class MenuInGame : FluidPanel
    {
        FluidLabel lblTime;
        StopWatch timerReference;

        public MenuInGame(int x, int y, int w, int h, StopWatch timer)
            : base(x, y, w, h)
        {
            timer.OneSecondTick += timer_Tick;
            timerReference = timer;
            refreshUndoRedoImages();
        }

        List<FluidControl> FirstPage = new List<FluidControl>();
        List<FluidControl> SecondPage = new List<FluidControl>();

        FluidButton btnRedo, btnUndo ;

        protected override void InitControl()
        {
            base.InitControl();
            EnableDoubleBuffer = false;

            const int gap = 2;
            const int nextPageButtonWidth = 20;
            const int nextPageButtonHeight = nextPageButtonWidth;
            int height = this.Height - 4 * gap;

            /*First*/
            FluidButton btnExit = new FluidButton(string.Empty, 5 * gap, 2 * gap, height, height);
            btnExit.Image = Resources.exit;
            btnExit.Click += new EventHandler(btnExit_Click);
            btnExit.Text = Resources.ExitLabel;
            btnExit.PaintButtonText += new EventHandler<FluidPaintEventArgs>(btn_PaintButtonText);
            btnExit.ForeColor = Color.Wheat;
            btnExit.BackColor = Color.Black;

            FluidButton btnConfiguration = new FluidButton(string.Empty, 5 * gap + height + gap, 2 * gap, height, height);
            btnConfiguration.Image = Resources.configuration;
            btnConfiguration.Click += new EventHandler(btnConfiguration_Click);
            btnConfiguration.Text = Resources.ConfigurationLabel;
            btnConfiguration.PaintButtonText += new EventHandler<FluidPaintEventArgs>(btn_PaintButtonText);
            btnConfiguration.BackColor = Color.Black;

            FluidButton btnRestart = new FluidButton(string.Empty, 5 * gap + height + gap + height + gap, 2 * gap, height, height);
            btnRestart.Image = Resources.restart;
            btnRestart.Text = Resources.RestartLabel;
            btnRestart.Click += new EventHandler(btnRestart_Click);
            btnRestart.PaintButtonText += new EventHandler<FluidPaintEventArgs>(btn_PaintButtonText);
            btnRestart.BackColor = Color.Black;

            Controls.Add(btnConfiguration);
            FirstPage.Add(btnConfiguration);
            Controls.Add(btnExit);
            FirstPage.Add(btnExit);
            Controls.Add(btnRestart);
            FirstPage.Add(btnRestart);

            /*Second*/
            btnUndo = new FluidButton(string.Empty, 5 * gap, 2 * gap, height, height);
            btnUndo.Image = Resources.undoImage;
            btnUndo.Click += new EventHandler(btnUndo_Click);
            btnUndo.Text = Resources.Undo;
            btnUndo.PaintButtonText += new EventHandler<FluidPaintEventArgs>(btn_PaintButtonText);
            btnUndo.ForeColor = Color.Wheat;
            btnUndo.BackColor = Color.Black;
            btnUndo.EnableCache = false;
            btnUndo.Visible = false;

            btnRedo = new FluidButton(string.Empty, 5 * gap + height + gap, 2 * gap, height, height);
            btnRedo.Image = Resources.redoImage;
            btnRedo.Click += new EventHandler(btnRedo_Click);
            btnRedo.Text = Resources.Redo;
            btnRedo.PaintButtonText += new EventHandler<FluidPaintEventArgs>(btn_PaintButtonText);
            btnRedo.ForeColor = Color.Wheat;
            btnRedo.BackColor = Color.Black;
            btnRedo.EnableCache = false;
            btnRedo.Visible = false;

            Controls.Add(btnUndo);
            SecondPage.Add(btnUndo);
            Controls.Add(btnRedo);
            SecondPage.Add(btnRedo);

            /*Common*/
            int timePositionLeft = 8 * gap + 3 * height;
            lblTime = new FluidLabel(":", timePositionLeft, gap + 20 + 5, this.Width - timePositionLeft - nextPageButtonWidth, 20);
            lblTime.Format.Alignment = StringAlignment.Center;

            FluidLabel lblTimeTitle = new FluidLabel(Resources.TimeElapsed, timePositionLeft, gap, this.Width - timePositionLeft, 20);
            lblTimeTitle.Font = new Font(FontFamily.GenericSansSerif, 7f, FontStyle.Regular);
            Controls.Add(lblTimeTitle);
            Controls.Add(lblTime);

            FluidButton btnNextPage = new FluidButton(string.Empty, this.Width - nextPageButtonWidth, (this.Height - nextPageButtonWidth) / 2, nextPageButtonWidth, nextPageButtonHeight);
            btnNextPage.Text = "...";
            btnNextPage.Click += new EventHandler(btnNextPage_Click);
            btnNextPage.PaintButtonText += new EventHandler<FluidPaintEventArgs>(btn_PaintButtonText);
            btnNextPage.BackColor = Color.Black;
            Controls.Add(btnNextPage);

        }
        
        /// <summary>
        /// Button exit clicked.
        /// </summary>
        public event EventHandler ExitClick;
        /// <summary>
        /// Button exit clicked.
        /// </summary>
        void btnExit_Click(object sender, EventArgs e)
        {
            if(ExitClick != null)
                ExitClick(sender, e);
        }

        /// <summary>
        /// Button configuration clicked.
        /// </summary>
        public event EventHandler ConfigurationClick;
        /// <summary>
        /// Button configuration clicked.
        /// </summary>
        void btnConfiguration_Click(object sender, EventArgs e)
        {
            if (ConfigurationClick != null)
                ConfigurationClick(sender, e);
        }

        /// <summary>
        /// Restart the game.
        /// </summary>
        public event EventHandler RestartClick;
        /// <summary>
        /// Button restart clicked - show confirmation dialog.
        /// </summary>
        void btnRestart_Click(object sender, EventArgs e)
        {
            MessageDialog msgReallyRestart = new MessageDialog();
            msgReallyRestart.Message = Resources.RestartGame;
            msgReallyRestart.OkText = Resources.RestartGameYes;
            msgReallyRestart.CancelText = Resources.RestartGameNo;
            msgReallyRestart.Result += new EventHandler<Fluid.Classes.DialogEventArgs>(msgReallyRestart_Result);
            msgReallyRestart.ShowModal(ShowTransition.FromBottom);
        }

        /// <summary>
        /// Restart the game - yes/no clicked
        /// </summary>
        void msgReallyRestart_Result(object sender, Fluid.Classes.DialogEventArgs e)
        {
            switch (e.Result)
            {
                case System.Windows.Forms.DialogResult.OK:
                    if (RestartClick != null)
                        RestartClick(sender, e);
                    break;
            }
        }

        /// <summary>
        /// Button change page - show confirmation dialog.
        /// </summary>
        void btnNextPage_Click(object sender, EventArgs e)
        {
            bool clickedInTheFirstPage = FirstPage[0].Visible;
            foreach (FluidControl cntrl in FirstPage)
            {
                cntrl.Visible = !clickedInTheFirstPage;
            }
            foreach (FluidControl cntrl in SecondPage)
            {
                cntrl.Visible = clickedInTheFirstPage;
            }
        }

        /// <summary>
        /// Button undo clicked.
        /// </summary>
        void btnUndo_Click(object sender, EventArgs e)
        {
            UndoFired(RevertingChanges.UndoRedoHistory.Undo());
        }

        /// <summary>
        /// Button redo click.
        /// </summary>
        void btnRedo_Click(object sender, EventArgs e)
        {
            RedoFired(RevertingChanges.UndoRedoHistory.Redo());
        }

        public void refreshUndoRedoImages()
        { 
            btnUndo.Image = RevertingChanges.UndoRedoHistory.CanUndo ? Resources.undoImage : Resources.undo_disabled;
            btnUndo.Enabled = RevertingChanges.UndoRedoHistory.CanUndo;

            btnRedo.Image = RevertingChanges.UndoRedoHistory.CanRedo ? Resources.redoImage : Resources.redo_disabled;
            btnRedo.Enabled = RevertingChanges.UndoRedoHistory.CanRedo;  
        }

        public delegate void UndoRedoDelegate(RevertingChanges.SudokuBoardAction e);
        /// <summary>
        /// Undo/redo called.
        /// </summary>
        public event UndoRedoDelegate UndoEvent;
        /// <summary>
        /// Undo/Redo - call.
        /// </summary>
        private void UndoFired(RevertingChanges.SudokuBoardAction e)
        {
            if (UndoEvent != null)
                UndoEvent(e);
        }

        /// <summary>
        /// Undo/redo called.
        /// </summary>
        public event UndoRedoDelegate RedoEvent;
        /// <summary>
        /// Undo/Redo - call.
        /// </summary>
        private void RedoFired(RevertingChanges.SudokuBoardAction e)
        {
            if (RedoEvent != null)
                RedoEvent(e);
        }

        public override void Show()
        {
            refreshUndoRedoImages();
            timer_Tick(timerReference.ElapsedTime);
            base.Show();
        }

        /// <summary>
        /// Show elapsed time.
        /// </summary>
        /// <param name="e">elapsed time in seconds</param>
        private void timer_Tick(double e)
        {
            TimeSpan elapsedTime = TimeSpan.FromSeconds(e);
            if (elapsedTime.Hours == 0)
                lblTime.Text = String.Format("{1}:{2}", elapsedTime.Hours, elapsedTime.Minutes, elapsedTime.Seconds.ToString("00"));
            else
                lblTime.Text = String.Format("{0}:{1}:{2}", elapsedTime.Hours, elapsedTime.Minutes.ToString("00"), elapsedTime.Seconds.ToString("00"));
        }

        void btn_PaintButtonText(object sender, FluidPaintEventArgs e)
        {
            FluidButton btn = (FluidButton)sender;
            Font smallFont = new Font(FontFamily.GenericSansSerif, 7f, FontStyle.Regular);
            StringFormat stringFormat = new StringFormat(StringFormatFlags.NoWrap);

            string text = btn.Text;
            Graphics g = e.Graphics;
            Rectangle rect = e.ControlBounds;
            
            if (btn.Image != null)
            {
                int imW = ScaleX(btn.Image.Width);
                int imH = ScaleY(btn.Image.Height);

                int w = Math.Min(imW, rect.Width);
                int h = Math.Min(imH, rect.Height);
                rect.Width = w - 5;
                rect.Height = h - 5;
                rect.X += 2;
                rect.Y += 2;

                if (btn.IsDown)
                {
                    rect.X++;
                    rect.Y++;
                }

                System.Drawing.Imaging.ImageAttributes attr = new System.Drawing.Imaging.ImageAttributes();
                //pruhledna
                attr.SetColorKey(Color.Fuchsia, Color.Fuchsia);

                g.DrawImage(btn.Image, rect, 0, 0, btn.Image.Width, btn.Image.Height, GraphicsUnit.Pixel, attr);
            }

            if (text.Length > 0)
            {
                Brush brush = new SolidBrush(Fluid.Classes.Theme.ThemeClass.Settings.NumpadForeColor);
                float smallWidth = e.ScaleFactor.Width * 5f + g.MeasureString(btn.Text, smallFont).Width;
                int dw = (int)((btn.Width - smallWidth) / 2f);
                int dh = (int)(2f * e.ScaleFactor.Width);
                RectangleF rf = RectFFromRect(rect);
                stringFormat.LineAlignment = StringAlignment.Far;
                stringFormat.Alignment = StringAlignment.Center;
                g.DrawString(btn.Text, smallFont, brush, rf, stringFormat);
            }
        }

    }
}
